<template>
    <div class="content" ref="content" id="content">
        <div class="targetModule" v-if="isCruise">
            <img :src="personalMode ? thirdPersonIcon : firstPersonIcon" alt="" @click="targetModule()">
        </div>
        <img src="/loading/home.png" v-if="!loadingPercentage.completed" class="gjp" alt="">
        <div ref="container" class="three-container"
            :style="{ width: `calc(100vw - ${containerOffsetLeft})`, height: `calc(100vh - ${containerOffsetTop})` }">
        </div>
        <BottomContent v-if="loadingPercentage.completed" :itemList="[]">
            <template #default>
                <div class="button-list" v-if="isGoBack">
                    <div class="button" @click="goBack">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            返回
                        </div>
                    </div>
                </div>
                <div class="button-list" v-if="playerController">
                    <div class="button" @click="removePlayerController">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            返回
                        </div>
                    </div>
                </div>
                <div class="button-list" v-if="!isGoBack && isCruise == '' && !playerController">
                    <div class="button" @click="customLine(null)">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            巡游路线规划
                        </div>
                    </div>
                    <div class="button" @click="toggleFirstPerson">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            第一人称漫游
                        </div>
                    </div>
                    <!-- <div class="button" @click="toggleThirdPerson">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            第三人称漫游
                        </div>
                    </div> -->
                    <div class="button" @click="escapeRouteNavigation">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            逃生路线导航
                        </div>
                    </div>
                    <div class="button" @click="randomTourRoute">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            随机巡游路线
                        </div>
                    </div>
                </div>
                <div class="button-list" v-if="isCruise">
                    <div class="button" @click="removeIsCruise">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            返回
                        </div>
                    </div>
                    <div class="button" @click="startCruise" v-if="isCruise == 'pause' || isCruise == 'edit'">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            开始巡航
                        </div>
                    </div>
                    <div class="button" @click="pauseCruise(false)" v-if="isCruise == 'start'">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            暂停巡航
                        </div>
                    </div>
                    <div class="button" @click="addLine" v-if="isCruise == 'edit'">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            添加路线点位
                        </div>
                    </div>
                    <div class="button" @click="removeLine" v-if="isCruise == 'edit'">
                        <img src="@/assets/three/button-background.svg" alt="">
                        <div class="label">
                            删除路线
                        </div>
                    </div>
                </div>
            </template>
        </BottomContent>

        <div class="xhmb" v-if="isCruise == 'pause' && modulePanel && startCruiseIndex >= 2">
            <div class="mb-title">
                <div>
                    巡航内容信息
                </div>
                <div>
                    <el-icon class="close-btn" @click="targetModulePanel(false)">
                        <Close />
                    </el-icon>
                </div>
            </div>
            <div class="mb-content">
                1. 当前站点信息正常
            </div>
        </div>
    </div>
</template>

<script setup async>
import { ref, onMounted, onBeforeUnmount, shallowRef, defineEmits, defineProps, nextTick, onUpdated } from 'vue'
import BottomContent from '@/components/BottomContent'
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'
import { RGBELoader } from 'three/examples/jsm/loaders/RGBELoader'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass'
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass'
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader'
import { OutputPass } from 'three/examples/jsm/postprocessing/OutputPass'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';
import { CSS2DRenderer, CSS2DObject } from "three/examples/jsm/renderers/CSS2DRenderer"
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
import { gsap } from 'gsap'
import { createBoundingPlanes } from '@/utils/three/BoundingPlanesGroup'
import Loading from '@/components/Loading'
import { useFullscreen } from '@vueuse/core'
import particleFire from 'three-particle-fire';
import { LineBuffer } from '@/utils/three/LineBuffre.js';
import { SplineEditor } from '@/utils/three/SplineEditor.js'
import AnimationsModule from './animations.js'
import 'animate.css/animate.min.css';
import  { Group, Tween, Easing } from '@tweenjs/tween.js'
import TWEEN from 'tween.js';
import { BeforeCompile } from './BeforeCompile.js';

import textBackground from '@/assets/three/text-bac.svg';
import lineBackground from '@/assets/three/line.svg';
// 在顶部引入
import PlayerController from './PlayerController.js';
// 第一和第三人称 icon
import firstPersonIcon from '@/assets/image/1.svg';
import thirdPersonIcon from '@/assets/image/3.svg';

import { WaterSpray } from './WaterSpray.js';



// 在 setup 中添加
const playerController = shallowRef(null);

const props = defineProps({
    outlinePass: {
        type: Boolean,
        default: false
    }
})
const emit = defineEmits(['loadingFinish', 'hideUI']);
// DOM 引用
const container = ref(null)
const containerOffsetLeft = ref('100px');
const containerOffsetTop = ref('85px');

const content = ref(null)
const { toggle } = useFullscreen(content)


// 1. 创建独立的tween组
const tweenGroup = new Group()

// 状态管理
const isGoBack = ref(false)
const isCruise = ref('')
const loadingPercentage = ref({
    percentage: '',
    completed: false
})
const firstPerson = ref(false);
// Three.js 核心对象
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, 1, 0.1, 70000)
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

let renderer = null;
let controls = null;
let composer = null;
let css2Renderer = null;
const gltfGroup = new THREE.Group()
const css2dRendererGroup = new THREE.Group()
const boundingPlanesGroup = new THREE.Group()
const fireGroup = new THREE.Group()
let particleFireMesh, outlinePass, splineEditor, activeModel;

// 巡航路径
let linePoints = [];
let curve = new THREE.CatmullRomCurve3(linePoints);

let animationss;

// 资源管理
const resources = {
    textures: [],
    models: [],
    geometries: [],
    materials: [],
    eventListeners: [],
    animations: []
}

// 相机巡航动画
const pathParams = {
    t: 0,
    lookAhead: 0.05,
    speed: 0.0004
}

// 巡航的各个点路线
let startCruisePositions = []
// 当前路线的索引
let startCruiseIndex = 0;

// 是否显示面板的显示 模块
let modulePanel = ref(false);

// 处理模型的 模块
let selectedForOutline = {
    'jiayaojian': [],
    'chendianchi': [],
    'tuoshuijifang': [],
    'shitang': [],
    'qingshuichi': [],
    'Vxinshuiche': [],
    'nonsuochi': [],
    'painichi': [],
};
defineExpose([
    scene,
    camera,
    renderer,
])
// 模型配置
const gltfArray = [
    { url: '/modules/home.glb', labelText: '', isBbox: false },
]
let lineBuffreMesh, lineBuffer;
const collidableMeshes = [];
// 人物
let figureGlb = null;
let mixer = null;


// 第一人称 第三人称切换
const personalMode = ref(false);
// 加载管理器
const loadingManager = new THREE.LoadingManager(
    () => {
        loadingPercentage.value.completed = true;
        emit('loadingFinish', scene);
    },
    (url, loaded, total) => {
        loadingPercentage.value.percentage = `加载中..${((loaded / total) * 100).toFixed(2)}%`
    }
)

const targetModule = (value) => {
    personalMode.value = !personalMode.value;
}

const targetModulePanel = (value) => {
    modulePanel.value = value;
}

// 
const addLine = () => {
    splineEditor.addPoint(new THREE.Vector3(Math.random() * 160 - 80, 9, Math.random() * 80 - 40));
}
const removeLine = () => {
    splineEditor.removePoint();
}
const customLine = (initialPositions) => {
    emit('hideUI', false);
    lineBuffer?.dispose();
    scene.remove(lineBuffreMesh);
    controls.maxPolarAngle = Math.PI * 0.5; // 最大俯角（避免完全倒置）
    controls.maxDistance = 160; // 最大缩放距离（默认Infinity）

    // 创建编辑器实例
    splineEditor = new SplineEditor({
        container: container.value,
        scene,
        camera,
        renderer,
        controls,
        initialPositions: initialPositions || [
            new THREE.Vector3(-84.3617583218016, 8.2, -10.849091356457286),
            new THREE.Vector3(-52.162864487552994, 8.2, -10.319223426060486),
            new THREE.Vector3(-46.07550935082634, 8.2, 25.93232602824),
            new THREE.Vector3(43.8446096812449, 8.2, 26.74476831281035)
        ]
    });
    isCruise.value = 'edit'; // 编辑模式

    modulePanel.value = true;
    css2dRendererGroup.children.forEach(item => item.visible = false);
}
const removeIsCruise = () => {
    splineEditor?.dispose(true);
    lineBuffer?.dispose();
    goBack();
}
// 安全获取 Object3D（容错：数组 / {object:...} / 直接就是 Object3D）
function asObject3D(entry) {
    if (!entry) return null;
    if (entry.isObject3D) return entry;
    if (Array.isArray(entry)) return entry[0] && entry[0].isObject3D ? entry[0] : null;
    if (entry.object && entry.object.isObject3D) return entry.object;
    return null;
}

// 计算 group(或任意 Object3D) 的世界包围盒（会自动更新矩阵并补 computeBoundingBox）
function getWorldBox(obj3d) {
    // 先确保 worldMatrix 是最新的
    obj3d.updateMatrixWorld(true);

    // 遍历所有子 Mesh，补几何体的 boundingBox
    obj3d.traverse((child) => {
        if (child.isMesh && child.geometry && !child.geometry.boundingBox) {
            try { child.geometry.computeBoundingBox(); } catch { }
        }
    });

    const box = new THREE.Box3();
    box.setFromObject(obj3d);
    return box;
}
const escapeRouteNavigation = () => {
    emit('hideUI', false);
    controls.maxPolarAngle = Math.PI * 0.5; // 最大俯角（避免完全倒置）
    let positons = [
        new THREE.Vector3(-86.12838084817687, 8.2, -22.957173782414927),
        new THREE.Vector3(-78.16769815059143, 8.2, -41.19260384109335),
        new THREE.Vector3(74.18100213938436, 8.2, -41.03001350400375),
        new THREE.Vector3(87.75785577340766, 8.2, -22.54794088333795)
    ]
    figureGlb.position.copy(positons[0]);
    curve = new THREE.CatmullRomCurve3(positons);
    curve.curveType = 'catmullrom';
    curve.tension = 0.2;

    // === 你原来的逻辑，改成用上面的工具函数 ===
    const obj3d = asObject3D(selectedForOutline['jiayaojian']);
    if (!obj3d) {
        console.warn('selectedForOutline[name] 不是有效的 Object3D：', selectedForOutline[name]);
    } else {
        const box = getWorldBox(obj3d);
        if (box.isEmpty()) {
            console.warn('该组没有有效几何体，包围盒为空：', obj3d);
        } else {
            const center = new THREE.Vector3();
            box.getCenter(center);
            initParticleFire(new THREE.Vector3(center.x, center.y - 2, center.z), 'jiayaojian');
        }
    }

    createLine(positons)

}


const loadingFbx = () => {
    const fbxload = new FBXLoader();
    fbxload.load('/modules/figure/people(1).fbx', (object) => {
        object.scale.set(0.01, 0.01, 0.01);
        figureGlb = object;
        // === 动画部分 ===
        const mixer1 = new THREE.AnimationMixer(object);
        mixer1.clipAction(object.animations[0]).play(); // walk
        mixer = mixer1;
        scene.add(object);
    }, (xhr) => {
    }, (error) => {
        console.log(error);

    });
}

const randomTourRoute = async () => {
    try {
        emit('hideUI', false);
        modulePanel.value = true;
        controls.maxPolarAngle = Math.PI * 0.5; // 最大俯角（避免完全倒置）
        let positons = [
            new THREE.Vector3(-80.41676031182031, 8.2, -41.260167728976064),
            new THREE.Vector3(0.24185417851266777, 8.2, -39.65343567141578),
            new THREE.Vector3(5.337754698764231, 8.2, 25.970116757927094),
            new THREE.Vector3(54.024371910018495, 8.2, 25.45775831527913)
        ]
        figureGlb.position.copy(positons[0]);
        customLine(positons);
        startCruise();
    } catch (error) {
        console.log('操作失败');
    }
}


const initParticleFire = (position, name) => {

    let fireHeight = 20;
    let particleCount = 600;

    let geometry0 = new particleFire.Geometry(8, fireHeight, particleCount);
    let material0 = new particleFire.Material({ color: 0xff0000, size: 10, depthTest: false, depthWrite: false });
    material0.setPerspective(camera.fov, window.innerHeight);
    particleFireMesh = new THREE.Points(geometry0, material0);
    particleFireMesh.position.copy(position);
    particleFireMesh.resetName = name;
    fireGroup.add(particleFireMesh);
}


const toggleFirstPerson = () => {
    emit('hideUI', false);
    createPlayerController({ firstPerson: true });
};
const createPlayerController = (options) => {
    if (playerController.value) {
        playerController.value.targetFirstPerson(!playerController.value.params.firstPerson);
        return;
    };
    playerController.value = new PlayerController(scene, camera, renderer.domElement, controls, options);
    playerController.value.setEnvironment(collidableMeshes[0]);
};
const removePlayerController = () => {
    playerController.value.dispose();
    playerController.value = null;
    controls = new OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
    nextTick(() => {
        goBack();
    })
};
const toggleThirdPerson = () => {
    createPlayerController();
};
const createLineCallBack = (linePoints) => {
    controls.minDistance = 0;  // 最小缩放距离（默认0）
    figureGlb.visible = true;
    personalMode.value = true;
    splineEditor?.removeSpline(startCruiseIndex);
    startCruiseIndex++;
    isCruise.value = 'start';
}

const createLine = (linePoints) => {
    let params = {
        path: linePoints, point: 200, pointsScale: 1, callback: () => createLineCallBack(linePoints)
    }
    const texture = new THREE.TextureLoader().load("/three/jt.png");
    texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
    texture.repeat.set(100, 1);
    gsap.to(texture.offset, {
        x: -10,
        duration: 10,
        repeat: -1,
        ease: 'none'
    })
    // 创建线缓冲对象
    lineBuffer = new LineBuffer(params);

    const materialBase = new THREE.MeshBasicMaterial({ map: texture, transparent: true })
    // 创建带有动画的网格
    lineBuffreMesh = lineBuffer.createAnimatedMesh(materialBase);
    scene.add(lineBuffreMesh);

    // 播放生长动画
    lineBuffer.animateGrowth(5);
}
// 初始化场景
const initScene = async () => {

    // 初始化渲染器
    renderer = new THREE.WebGLRenderer({
        antialias: true,
        logarithmicDepthBuffer: true
    })
    renderer.outputEncoding = THREE.sRGBEncoding; // 色彩空间
    renderer.toneMapping = THREE.ACESFilmicToneMapping; // 色调映射

    renderer.toneMappingExposure = 1.2; // 曝光度（间接影响环境亮度） 白天
    updateRendererSize()
    container.value.appendChild(renderer.domElement)
    camera.position.set(-10, 60, 70)
    camera.updateProjectionMatrix()

    // const axesHelper = new THREE.AxesHelper(1000);
    // scene.add(axesHelper);
    // 初始化控制器
    controls = new OrbitControls(camera, renderer.domElement)
    controls.enableDamping = true
    controls.target.set(-10, 0, 10)
    controls.minDistance = 10;  // 最小缩放距离（默认0）
    controls.maxDistance = 160; // 最大缩放距离（默认Infinity）
    controls.maxPolarAngle = Math.PI * 0.4; // 最大俯角（避免完全倒置）
    // 设置场景背景
    scene.background = new THREE.Color('#02004d')

    // 加载模型动画集合
    animationss = new AnimationsModule({ tweenGroup, Tween, Easing });

    // 初始化后期处理和标签渲染器
    initPostProcessing()
    createCSS2DRenderer()

    // const axesHelper = new THREE.AxesHelper(100);
    // scene.add(axesHelper);
    // 加载模型和环境
    gltfArray.forEach((item) => {
        loadModel(item)
    })
    loadingFbx();

    loadEnvironment()

    scene.add(gltfGroup)
    scene.add(css2dRendererGroup)
    scene.add(boundingPlanesGroup)
    scene.add(fireGroup)
    // 线性雾：颜色、开始距离、结束距离
    // scene.fog = new THREE.Fog(0xCCCCCC, 100, 700);

    // // 建议把背景色与雾色一致
    // scene.background = new THREE.Color(0xCCCCCC);

    
}

// 创建标签
const createLabel = (text) => {
    const label = document.createElement("div")
    label.style.cursor = 'pointer';
    label.style.pointerEvents = 'auto';
    label.innerHTML = `
        <div class='animate__animated animate__bounceIn' style="display: flex;align-items: center;flex-direction: column;justify-content: center;">
            <div style="width:120px;height: 50px;position: relative;">
                <img src="${textBackground}" style="width:120px;height: 50px;" />
                <div class="label-text" style="position:absolute;top:11.5px;left:0;right:0;margin: 0 auto;text-align: center;color:#fff;">${text}</div>    
            </div>
            <img src="${lineBackground}" style="width: 3px;height: 40px;margin-top: -5px;" />    
        </div>
    `
    return label
}

// 创建CSS2D渲染器
const createCSS2DRenderer = () => {
    css2Renderer = new CSS2DRenderer()
    updateCSS2DRendererSize()
    css2Renderer.domElement.style.position = 'absolute'
    css2Renderer.domElement.style.top = '0'
    css2Renderer.domElement.style.pointerEvents = 'none'
    container.value.appendChild(css2Renderer.domElement)
}

// 初始化后期处理
const initPostProcessing = () => {
    composer = new EffectComposer(renderer)

    // 添加RenderPass（带色调映射）
    const renderPass = new RenderPass(scene, camera);
    renderPass.toneMapping = renderer.toneMapping;
    renderPass.toneMappingExposure = renderer.toneMappingExposure;
    composer.addPass(renderPass);

    const fxaaPass = new ShaderPass(FXAAShader)
    const pixelRatio = renderer.getPixelRatio()
    fxaaPass.material.uniforms['resolution'].value.x = 1 / (container.value.clientWidth * pixelRatio)
    fxaaPass.material.uniforms['resolution'].value.y = 1 / (container.value.clientHeight * pixelRatio)
    composer.addPass(fxaaPass)

    const outputPass = new OutputPass();
    outputPass.toneMapping = THREE.NoToneMapping; // 避免二次处理
    outputPass.outputColorSpace = THREE.sRGBColorSpace; // r152+
    composer.addPass(outputPass);

    if (props.outlinePass) {
        // 4. 创建描边效果
        outlinePass = new OutlinePass(
            new THREE.Vector2(container.value.clientWidth, container.value.clientHeight),
            scene,
            camera
        );
        outlinePass.edgeStrength = 3.0; // 描边强度
        outlinePass.edgeGlow = 0.5;     // 边缘发光
        outlinePass.edgeThickness = 1.0; // 边缘厚度
        outlinePass.pulsePeriod = 2;    // 脉冲周期
        outlinePass.visibleEdgeColor.set('#ff0000'); // 可见边颜色
        outlinePass.hiddenEdgeColor.set('#ff0000');  // 隐藏边颜色
        composer.addPass(outlinePass);
        window.addEventListener('mousemove', onMouseMove);
    }
}


function onMouseMove(event) {
    // 获取容器相对于视口的坐标位置
    const rect = container.value.getBoundingClientRect();

    // 计算容器内的相对鼠标坐标 (考虑滚动偏移)
    const mouseX = event.clientX - rect.left;
    const mouseY = event.clientY - rect.top;

    // 转换为标准化设备坐标 (NDC: -1到1)
    mouse.x = (mouseX / rect.width) * 2 - 1;
    mouse.y = -(mouseY / rect.height) * 2 + 1;

    // 更新射线检测
    raycaster.setFromCamera(mouse, camera);
    const intersects = raycaster.intersectObjects(scene.children);
    // 更新描边对象
    outlinePass.selectedObjects = intersects.length > 0 ? [intersects[0].object.parent] : [];
}


// 加载环境贴图
const loadEnvironment = () => {
    // 设置天空盒子
    const loader = new THREE.TextureLoader();
    const tex = loader.load('/hdre_426_meadow_hill_hdri.jpg', () => {
        tex.mapping = THREE.EquirectangularReflectionMapping;  // 或者直接用球面贴图
        tex.colorSpace = THREE.SRGBColorSpace;
        scene.background = tex;        // 只当背景
        tex.anisotropy = renderer.capabilities.getMaxAnisotropy();
        // 可选：也用作环境（让建筑有“天空反射”）
    });
    // 设置天空盒子
    const textureCubeLoader = new THREE.CubeTextureLoader();
    const textureCube = textureCubeLoader.load([
        '/textureCube/posx.jpg',
        '/textureCube/negx.jpg',
        '/textureCube/posy.jpg',
        '/textureCube/negy.jpg',
        '/textureCube/posz.jpg',
        '/textureCube/negz.jpg',
    ]);
    scene.environment = textureCube;
    const ambient = new THREE.AmbientLight(0xf5f5f5, 2);
    scene.add(ambient);
}
// 加载模型
const loadModel = ({ url, labelText, isBbox, sg }) => {
    const loader = new GLTFLoader(loadingManager)
    const dracoLoader = new DRACOLoader()
    dracoLoader.setDecoderPath("/draco/gltf/")
    dracoLoader.setDecoderConfig({ type: "js" })
    loader.setDRACOLoader(dracoLoader)

    loader.load(url, (gltf) => {
        const model = gltf.scene
        resources.models.push(model)
        model.traverse((item) => {
            if (item.isMesh) {
                if (item.name == 'EXPORT_GOOGLE_SAT_WM') {
                    const texture = item.material.map;
                    item.material = new THREE.MeshBasicMaterial({ map: texture });
                }
            }
            const [name, id] = item.name.split('_');
            if (['shang', 'qian', 'zuo', 'you', 'hou', 'YOU'].includes(id?.replace(/\d/g, ''))) {
                if (!selectedForOutline[name]) selectedForOutline[name] = [];
                selectedForOutline[name].push(...item.children);
            }
        })
        collidableMeshes.push(model)
        model.resetName = labelText
        gltfGroup.add(model)
    }, (error) => {

    })
}

// 更新渲染器尺寸
const updateRendererSize = () => {
    if (!container.value) return

    const width = container.value.clientWidth
    const height = container.value.clientHeight

    camera.aspect = width / height
    camera.updateProjectionMatrix()
    renderer?.setSize(width, height)

    // 更新后期处理器
    if (composer) {
        composer.setSize(width, height)
        const passes = composer.passes
        for (let i = 0; i < passes.length; i++) {
            if (passes[i] instanceof ShaderPass && passes[i].material.uniforms['resolution']) {
                const pixelRatio = renderer.getPixelRatio()
                passes[i].material.uniforms['resolution'].value.x = 1 / (width * pixelRatio)
                passes[i].material.uniforms['resolution'].value.y = 1 / (height * pixelRatio)
            }
        }
    }
}

// 更新CSS2D渲染器尺寸
const updateCSS2DRendererSize = () => {
    if (!container.value || !css2Renderer) return
    const width = container.value.clientWidth
    const height = container.value.clientHeight
    css2Renderer.setSize(width, height)
}

// 巡航控制
const startCruise = () => {
    if (isCruise.value === 'start') return

    if (!lineBuffreMesh) {
        const [positons] = splineEditor.getPositions();
        figureGlb.position.copy(positons[0]);
        startCruisePositions = positons;
        splineEditor.dispose();
        linePoints = positons;
        curve = new THREE.CatmullRomCurve3(positons);
        curve.curveType = 'catmullrom';
        curve.tension = 0.2;
        createLine(linePoints);
    } else {
        isCruise.value = 'start';
        modulePanel.value = true;
    }
}

const pauseCruise = (value) => {
    isCruise.value = 'pause'
}

// 返回初始视图
const goBack = () => {
    isGoBack.value = false;
    modulePanel.value = false; // 关闭面板显示
    isCruise.value = '';
    pathParams.t = 0;
    controls.minDistance = 10;  // 最小缩放距离（默认0）
    controls.maxDistance = 160; // 最大缩放距离（默认Infinity）
    controls.maxPolarAngle = Math.PI * 0.35; // 最大俯角（避免完全倒置）

    scene.remove(lineBuffreMesh);
    lineBuffreMesh = null;
    animationss.reset(animationss.key);

    // 显示所有模型
    gltfGroup.children.forEach(child => child.visible = true)
    css2dRendererGroup.children.forEach(child => child.visible = true)
    boundingPlanesGroup.children.forEach(child => child.visible = true)
    fireGroup.children.forEach(child => fireGroup.remove(child));
    figureGlb.visible = false; // 隐藏人物

    // 关闭巡航的 参数 
    startCruiseIndex = 0;
    startCruisePositions = [];

    // 相机位置动画
    const cameraTween = new Tween(camera.position, tweenGroup)
        .to({
            x: -10, y: 60, z: 70
        }, 1500)
        .easing(Easing.Quartic.InOut)
        .onUpdate(() => controls?.update())
        .start().onComplete(() => {
            emit('hideUI', true);
            tweenGroup.remove(cameraTween)
        });

    // 控制目标动画
    const targetTween = new Tween(controls.target, tweenGroup)
        .to({
            x: -10,
            y: 0,
            z: 10,
        }, 800)
        .easing(Easing.Quartic.InOut)
        .start().onComplete(() => tweenGroup.remove(targetTween));
}


const yourCompletionCallback = () => {
    isCruise.value = 'pause';
}
const animateThirdPersonCamera = (delta) => {
    // 1. 计算当前点和下一个目标点
    const currentPoint = curve.getPointAt(pathParams.t);

    // 2. 计算目标点（确保不超过1）
    const targetT = Math.min(pathParams.t + pathParams.lookAhead, 1); // 不超过1
    const targetPoint = curve.getPointAt(targetT);

    // 3. 检查是否到达终点
    const isComplete = pathParams.t >= 1 - pathParams.speed; // 接近终点时视为完成
    if (!isComplete) {
        const offset = new THREE.Vector3(0, 2, -3);

        resources.animations.push(
            // 偏移：相机在人物后上方一点
            gsap.to(figureGlb.position, {
                x: currentPoint.x,
                y: currentPoint.y,
                z: currentPoint.z,
                duration: 0.4,
                ease: 'none',
                onUpdate() {
                    const currentTargetT = Math.min(pathParams.t + pathParams.lookAhead, 1);
                    const currentTargetPoint = curve.getPointAt(currentTargetT);
                    figureGlb.lookAt(currentTargetPoint);

                    // 更新相机跟随
                    const worldOffset = offset.clone().applyQuaternion(figureGlb.quaternion);
                    camera.position.copy(figureGlb.position).add(worldOffset);

                    // 相机看向人物
                    controls.target.copy(figureGlb.position.clone().add(new THREE.Vector3(0, 1, 0)));
                    controls.update();
                }
            })
        );
        mixer?.update(delta);
        // 判断是否到达 指定位置 巡航
        if (startCruisePositions.length) {
            const distance = figureGlb.position.distanceTo(startCruisePositions[startCruiseIndex]);
            if (distance <= 4 || isComplete) {
                pauseCruise();

                splineEditor?.removeSpline(startCruiseIndex);
                startCruiseIndex++;

                if (startCruiseIndex < startCruisePositions.length) {
                    setTimeout(() => {
                        startCruise();
                    }, 3000);
                } else {
                    startCruisePositions = [];
                    startCruiseIndex = 0;
                }
                return;
            }
        }

        // 4. 更新进度（不超过1）
        pathParams.t = Math.min(pathParams.t + pathParams.speed, 1);
    } else {
        // 已经到达终点，执行完成回调
        console.log("已到达路径终点");
        yourCompletionCallback();
    }
};

const animateFirstCamera = () => {
    // 1. 计算当前点和下一个目标点
    const currentPoint = curve.getPointAt(pathParams.t);

    // 2. 计算目标点（确保不超过1）
    const targetT = Math.min(pathParams.t + pathParams.lookAhead, 1); // 不超过1
    const targetPoint = curve.getPointAt(targetT);

    // 3. 检查是否到达终点
    const isComplete = pathParams.t >= 1 - pathParams.speed; // 接近终点时视为完成



    // 判断是否到达 指定位置 巡航
    if (startCruisePositions.length) {
        const distance = camera.position.distanceTo(startCruisePositions[startCruiseIndex]);
        if (distance <= 4 || isComplete) {
            pauseCruise();

            splineEditor.removeSpline(startCruiseIndex);
            startCruiseIndex++;

            if (startCruiseIndex < startCruisePositions.length) {
                setTimeout(() => {
                    startCruise();
                }, 3000);
            } else {
                startCruisePositions = [];
                startCruiseIndex = 0;
            }
            return;
        }
    }

    if (!isComplete) {
        resources.animations.push(
            gsap.to(camera.position, {
                x: currentPoint.x,
                y: currentPoint.y + 2,
                z: currentPoint.z,
                duration: 0.5,
                ease: 'none',
                onUpdate() {
                    // 更新目标点（防止回跳）
                    const currentTargetT = Math.min(pathParams.t + pathParams.lookAhead, 1);
                    const currentTargetPoint = curve.getPointAt(currentTargetT);
                    controls.target.copy(new THREE.Vector3(
                        currentTargetPoint.x,
                        currentTargetPoint.y + 2,
                        currentTargetPoint.z
                    ));
                },
            })
        );


        // 4. 更新进度（不超过1）
        pathParams.t = Math.min(pathParams.t + pathParams.speed, 1);
    } else {
        // 已经到达终点，执行完成回调
        console.log("已到达路径终点");
        yourCompletionCallback();
    }
};

let clock = new THREE.Clock();

onUpdated(() => {
    console.log('管线了');

})

// 主动画循环
const animate = () => {
    if (!container.value) return
    let delta = clock.getDelta();

    const rect = container.value.getBoundingClientRect()
    if (rect) {
        containerOffsetLeft.value = rect.left + 'px';
        containerOffsetTop.value = rect.top + 'px';
        renderer?.setSize(rect.width, rect.height)
        camera.aspect = rect.width / rect.height
        camera.updateProjectionMatrix()
        css2Renderer?.setSize(rect.width, rect.height)
        css2Renderer?.render(scene, camera)
    }

    composer?.render()
    controls.enabled && controls?.update();

    if (isCruise.value === 'start') {

        // 第一人称和第三人称
        if (personalMode.value) {
            animateThirdPersonCamera(delta);
        } else {
            animateFirstCamera();
        }

    }
    fireGroup.children.forEach(child => {
        child?.material?.update(delta);
    })

    // if (lineBuffreMesh) {
    //     lineBuffreMesh.material.userData.uniforms.uTime.value += 0.1;
    //     console.log(lineBuffreMesh.material.userData.uniforms.uTime.value);

    // }

    // 更新 Tween 动画
    tweenGroup.update();

    playerController.value?.update(delta);

    requestAnimationFrame(animate)
}

// 窗口大小变化处理
const handleResize = () => {
    updateRendererSize()
    updateCSS2DRendererSize()
}

// 组件挂载
onMounted(() => {
    try {
        particleFire?.install({ THREE: THREE });
        particleFire?.init();
    } catch (e) {
        console.log(e)
    }


    initScene()
    animate()

    window.addEventListener('resize', handleResize)
})

// 组件卸载前清理
onBeforeUnmount(() => {
    // 移除事件监听
    window.removeEventListener('resize', handleResize)
    window.removeEventListener('mousemove', onMouseMove);

    // 清理动画
    resources.animations.forEach(anim => anim.kill())

    // 清理事件监听器
    resources.eventListeners.forEach(({ element, handler }) => {
        element?.removeEventListener('click', handler)
    })

    // 清理场景
    scene.traverse(object => {
        if (!object.isMesh) return

        if (object.geometry) {
            object.geometry.dispose()
        }

        if (object.material) {
            if (Array.isArray(object.material)) {
                object.material.forEach(m => m.dispose())
            } else {
                object.material.dispose()
            }
        }
    })
    // 清理纹理
    resources.textures.forEach(texture => {
        texture.dispose()
        texture.image?.close?.()
    })

    // 清理渲染器
    if (renderer) {
        container.value?.removeChild(renderer.domElement)
        renderer.dispose()
    }

    // 清理CSS2D渲染器
    if (css2Renderer) {
        container.value?.removeChild(css2Renderer.domElement)
    }

    // 清理控制器
    controls?.dispose();

    playerController.value?.dispose();

    // 清理GSAP
    gsap.globalTimeline.clear();

    tweenGroup.removeAll();



})
</script>

<style scoped lang="scss">
.three-container {
    width: calc(100vw - v-bind(containerOffsetLeft));
    // width: calc(90.8vw) ;
    height: calc(92.5vh);
    position: relative;
    overflow: hidden;
}

.content {
    width: 100%;
    height: 100%;
    position: relative;
}

.bottom-content {
    display: flex;
}

.button-list {
    display: flex;
    justify-content: center;
    width: 100%;

    .button {
        position: relative;
        width: 132px;
        height: 60px;
        text-align: center;
        line-height: 50px;
        cursor: pointer;
        margin: 0 20px;

        >img {
            position: absolute;
            z-index: -1;
            left: 0;
            width: 132px;
            height: 60px;
        }

        .label {
            width: 132px;
            font-size: 16px;
            text-align: center;
            color: #66FFFF;
        }
    }
}

.gjp {
    position: absolute;
    height: 100%;
    width: 100%;
    z-index: 999;
}

.targetModule {
    position: absolute;
    top: 140px;
    z-index: 9999;
    right: 480px;

    img {
        width: 40px;
    }
}

.xhmb {
    position: absolute;
    z-index: 999;
    width: 300px;
    height: 350px;
    background: rgba(#000, 0.4);
    top: 300px;
    right: 500px;
    border-radius: 10px;
    border: 1px solid #66FFFF;
    color: #fff;

    .mb-title {
        height: 30px;
        font-size: 20px;
        margin-bottom: 20px;
        display: flex;
        justify-content: space-between;
        padding: 10px 10px;

        .close-btn {
            font-size: 30px;
            cursor: pointer;
        }
    }

    .mb-content {
        padding: 0 10px;
        font-size: 16px;
        line-height: 30px;
        padding-left: 20px;
    }
}
</style>